<html>
<META http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<head>
<title>Section 16.5.&nbsp; Data Transfer</title>
<link rel="STYLESHEET" type="text/css" href="images/style.css">
<link rel="STYLESHEET" type="text/css" href="images/docsafari.css">
</head>
<body>
<table width="100%" border="0" cellspacing="0" cellpadding="0">
<tr><td><div STYLE="MARGIN-LEFT: 0.15in;"><a href="toc.html"><img src="images/team.gif" width="60" height="17" border="0" align="absmiddle"  alt="Team BBL"></a></div></td>
<td align="right"><div STYLE="MARGIN-LEFT: 0.15in;">
<a href=ch16lev1sec4.html><img src="images/prev.gif" width="60" height="17" border="0" align="absmiddle" alt="Previous Page"></a>
<a href=ch16lev1sec6.html><img src="images/next.gif" width="60" height="17" border="0" align="absmiddle" alt="Next Page"></a>
</div></td></tr></table>
<br><table width="100%" border="0" cellspacing="0" cellpadding="0"><tr><td valign="top"><a name="ch16lev1sec5"></a>
<h3 class="docSection1Title">16.5. Data Transfer</h3>
<p class="docText">Since a socket endpoint is represented as a file descriptor, we can use <tt>read</tt> and <tt>write</tt> to communicate with a socket, as long as it is connected. Recall that a datagram socket can be &quot;connected&quot; if we set the default peer address using the <tt>connect</tt> function. Using <tt>read</tt> and <tt>write</tt> with socket descriptors is significant, because it means that we can pass socket descriptors to functions that were originally designed to work with local files. We can also arrange to pass the socket descriptors to child processes that execute programs that know nothing about sockets.</P>
<p class="docText">Although we can exchange data using <tt>read</tt> and <tt>write</tt>, that is about all we can do with these two functions. If we want to specify options, receive packets from multiple clients, or send out-of-band data, we need to use one of the six socket functions designed for data transfer.</P>
<p class="docText">Three functions are available for sending data, and three are available for receiving data. First, we'll look at the ones used to send data.</p>
<p class="docText">The simplest one is <tt>send</tt>. It is similar to <tt>write</tt>, but allows us to specify flags to change how the data we want to transmit is treated.</P>
<a name="inta281"></a><P><table cellspacing="0" class="allBorders" border="1" RULES="none" cellpadding="5"><colgroup><col width="550"></colgroup><thead></thead><TR><td class="docTableCell" align="left" valign="top"><p class="docText">
<a name="PLID0"></a><div class="v1"><a href="ch16lev1sec5.html#PLID0">[View full width]</a></div><pre>
#include &lt;sys/socket.h&gt;

ssize_t send(int <span class="docEmphItalicAlt">sockfd</span>, const void *<span class="docEmphItalicAlt">buf</span>, size_t
<img border="0" width="14" height="9" alt="" align="left" src="images/ccc.gif"> <span class="docEmphItalicAlt">nbytes</span>, int <span class="docEmphItalicAlt">flags</span>);</pre><BR>
</P></TD></tr><TR><td class="docTableCell" align="right" valign="top"><p class="docText">Returns: number of bytes sent if OK, 1 on error</P></TD></TR></table></p><BR>
<p class="docText">Like <tt>write</tt>, the socket has to be connected to use <tt>send</tt>. The <span class="docEmphasis">buf</span> and <span class="docEmphasis">nbytes</span> arguments have the same meaning as they do with <tt>write</tt>.</P>
<p class="docText">Unlike <tt>write</tt>, however, <tt>send</tt> supports a fourth <span class="docEmphasis">flags</span> argument. Two flags are defined by the Single UNIX Specification, but it is common for implementations to support additional ones. They are summarized in <a class="docLink" href="#ch16fig11">Figure 16.11</a>.</p>
<a name="ch16fig11"></a><P><table cellspacing="0" class="allBorders" border="1" RULES="groups" cellpadding="5"><caption><H5 class="docTableTitle">Figure 16.11. Flags used with <tt>send</tt> socket calls</h5></caption><colgroup><col width="100"><col width="150"><col width="50"><col width="50"><col width="50"><col width="50"><col width="50"></colgroup><thead><tr><th class="rightBorder bottomBorder thead" scope="col" align="center" valign="middle"><p class="docText"><span class="docEmphRoman">Flag</span></p></th><th class="rightBorder bottomBorder thead" scope="col" align="center" valign="middle"><p class="docText"><span class="docEmphRoman">Description</span></p></th><th class="rightBorder bottomBorder thead" scope="col" align="center" valign="middle"><p class="docText"><span class="docEmphRoman">POSIX.1</span></P></th><th class="rightBorder bottomBorder thead" scope="col" align="center" valign="middle"><p class="docText"><span class="docEmphRoman">FreeBSD 5.2.1</span></p></th><th class="rightBorder bottomBorder thead" scope="col" align="center" valign="middle"><p class="docText"><span class="docEmphRoman">Linux 2.4.22</span></P></th><th class="rightBorder bottomBorder thead" scope="col" align="center" valign="middle"><p class="docText"><span class="docEmphRoman">Mac OS X 10.3</span></p></th><th class="bottomBorder thead" scope="col" align="center" valign="middle"><p class="docText"><span class="docEmphRoman">Solaris 9</span></P></th></tr></thead><tr><td class="rightBorder" align="left" valign="top"><p class="docText"><tt>MSG_DONTROUTE</tt></p></td><td class="rightBorder" align="left" valign="top"><p class="docText">Don't route packet outside of local network.</p></td><td class="rightBorder" align="left" valign="top">&nbsp;</td><td class="rightBorder" align="center" valign="top"><p class="docText">&#8226;</p></td><td class="rightBorder" align="center" valign="top"><p class="docText">&#8226;</p></td><td class="rightBorder" align="center" valign="top"><p class="docText">&#8226;</P></TD><td class="docTableCell" align="center" valign="top"><p class="docText">&#8226;</P></TD></TR><tr><TD class="rightBorder" align="left" valign="top"><p class="docText"><tt>MSG_DONTWAIT</tt></P></TD><td class="rightBorder" align="left" valign="top"><p class="docText">Enable nonblocking operation (equivalent to using <tt>O_NONBLOCK</tt>).</P></td><TD class="rightBorder" align="left" valign="top">&nbsp;</TD><TD class="rightBorder" align="center" valign="top"><p class="docText">&#8226;</p></TD><TD class="rightBorder" align="center" valign="top"><p class="docText">&#8226;</p></TD><TD class="rightBorder" align="center" valign="top"><p class="docText">&#8226;</p></td><td class="docTableCell" align="left" valign="top">&nbsp;</td></TR><tr><TD class="rightBorder" align="left" valign="top"><p class="docText"><tt>MSG_EOR</tt></p></TD><td class="rightBorder" align="left" valign="top"><p class="docText">This is the end of record if supported by protocol.</p></td><td class="rightBorder" align="center" valign="top"><p class="docText">&#8226;</p></td><td class="rightBorder" align="center" valign="top"><p class="docText">&#8226;</p></td><td class="rightBorder" align="center" valign="top"><p class="docText">&#8226;</p></td><td class="rightBorder" align="center" valign="top"><p class="docText">&#8226;</p></td><td class="docTableCell" align="left" valign="top">&nbsp;</td></TR><TR><td class="rightBorder" align="left" valign="top"><p class="docText"><tt>MSG_OOB</tt></P></TD><TD class="rightBorder" align="left" valign="top"><p class="docText">Send out-of-band data if supported by protocol (see <a class="docLink" href="ch16lev1sec7.html#ch16lev1sec7">Section 16.7</a>).</p></TD><TD class="rightBorder" align="center" valign="top"><p class="docText">&#8226;</P></td><TD class="rightBorder" align="center" valign="top"><p class="docText">&#8226;</p></TD><TD class="rightBorder" align="center" valign="top"><p class="docText">&#8226;</P></td><TD class="rightBorder" align="center" valign="top"><p class="docText">&#8226;</P></td><TD class="docTableCell" align="center" valign="top"><p class="docText">&#8226;</P></td></tr></table></p><br>
<p class="docText"><a name="idd1e123736"></a><a name="idd1e123741"></a><a name="idd1e123746"></a><a name="idd1e123749"></a><a name="idd1e123754"></a><a name="idd1e123757"></a><a name="idd1e123760"></a><a name="idd1e123765"></a><a name="idd1e123770"></a><a name="idd1e123775"></a><a name="idd1e123780"></a><a name="idd1e123785"></a><a name="idd1e123790"></a><a name="idd1e123795"></a><a name="idd1e123802"></a><a name="idd1e123807"></a><a name="idd1e123814"></a><a name="idd1e123817"></a>If <tt>send</tt> returns success, it doesn't necessarily mean that the process at the other end of the connection receives the data. All we are guaranteed is that when <tt>send</tt> succeeds, the data has been delivered to the network drivers without error.</P>
<p class="docText">With a protocol that supports message boundaries, if we try to send a single message larger than the maximum supported by the protocol, <tt>send</tt> will fail with <tt>errno</tt> set to <tt>EMSGSIZE</tt>. With a byte-stream protocol, <tt>send</tt> will block until the entire amount of data has been transmitted.</p>
<p class="docText">The <tt>sendto</tt> function is similar to <tt>send</tt>. The difference is that <tt>sendto</tt> allows us to specify a destination address to be used with connectionless sockets.</P>
<a name="inta282"></a><p><table cellspacing="0" class="allBorders" border="1" RULES="none" cellpadding="5"><colgroup><col width="550"></colgroup><thead></thead><TR><td class="docTableCell" align="left" valign="top"><p class="docText">
<a name="PLID1"></a><div class="v1"><a href="ch16lev1sec5.html#PLID1">[View full width]</a></div><pre>
#include &lt;sys/socket.h&gt;

ssize_t sendto(int <span class="docEmphItalicAlt">sockfd</span>, const void *<span class="docEmphItalicAlt">buf</span>, size_t
<img border="0" width="14" height="9" alt="" align="left" src="images/ccc.gif"> <span class="docEmphItalicAlt">nbytes</span>, int <span class="docEmphItalicAlt">flags</span>,
               const struct sockaddr *<span class="docEmphItalicAlt">destaddr</span>,
<img border="0" width="14" height="9" alt="" align="left" src="images/ccc.gif"> socklen_t <span class="docEmphItalicAlt">destlen</span>);
</pre><br>
</p></td></tr><tr><td class="docTableCell" align="right" valign="top"><p class="docText">Returns: number of bytes sent if OK, 1 on error</p></td></tr></table></p><br>
<p class="docText">With a connection-oriented socket, the destination address is ignored, as the destination is implied by the connection. With a connectionless socket, we can't use <tt>send</tt> unless the destination address is first set by calling <tt>connect</tt>, so <tt>sendto</tt> gives us an alternate way to send a message.</p>
<p class="docText">We have one more choice when transmitting data over a socket. We can call <tt>sendmsg</tt> with a <tt>msghdr</tt> structure to specify multiple buffers from which to transmit data, similar to the <tt>writev</tt> function (<a class="docLink" href="ch14lev1sec7.html#ch14lev1sec7">Section 14.7</a>).</p>
<a name="inta283"></a><p><table cellspacing="0" class="allBorders" border="1" RULES="none" cellpadding="5"><colgroup><col width="550"></colgroup><thead></thead><tr><td class="docTableCell" align="left" valign="top"><p class="docText">
<a name="PLID2"></a><div class="v1"><a href="ch16lev1sec5.html#PLID2">[View full width]</a></div><pre>
#include &lt;sys/socket.h&gt;

ssize_t sendmsg(int <span class="docEmphItalicAlt">sockfd</span>, const struct msghdr
<img border="0" width="14" height="9" alt="" align="left" src="images/ccc.gif"> *<span class="docEmphItalicAlt">msg</span>, int <span class="docEmphItalicAlt">flags</span>);</pre><BR>

</P></td></TR><TR><TD class="docTableCell" align="right" valign="top"><p class="docText">Returns: number of bytes sent if OK, 1 on error</p></TD></TR></table></P><br>
<p class="docText">POSIX.1 defines the <tt>msghdr</tt> structure to have at least the following members:</P>

<pre>
   struct msghdr {
     void          *msg_name;         /* optional address */
     socklen_t      msg_namelen;      /* address size in bytes */
     struct iovec  *msg_iov;          /* array of I/O buffers */
     int            msg_iovlen;       /* number of elements in array */
     void          *msg_control;      /* ancillary data */
     socklen_t      msg_controllen;   /* number of ancillary bytes */
     int            msg_flags;        /* flags for received message */
     .
     .
     .
   };
</pre><br>

<p class="docText">We saw the <tt>iovec</tt> structure in <a class="docLink" href="ch14lev1sec7.html#ch14lev1sec7">Section 14.7</a>. We'll see the use of ancillary data in <a class="docLink" href="ch17lev1sec4.html#ch17lev2sec6">Section 17.4.2</a>.</P>
<p class="docText">The <tt>recv</tt> function is similar to <tt>read</tt>, but allows us to specify some options to control how we receive the data.</P>
<a name="inta267"></a><P><table cellspacing="0" class="allBorders" border="1" RULES="none" cellpadding="5"><colgroup><col width="550"></colgroup><thead></thead><tr><TD class="docTableCell" align="left" valign="top"><p class="docText"><a name="idd1e124011"></a><a name="idd1e124016"></a><a name="idd1e124021"></a><a name="idd1e124026"></a><a name="idd1e124033"></a><a name="idd1e124038"></a><a name="idd1e124045"></a><a name="idd1e124050"></a><a name="idd1e124055"></a><a name="idd1e124060"></a><a name="idd1e124065"></a><a name="idd1e124070"></a>
<a name="PLID4"></a><div class="v1"><a href="ch16lev1sec5.html#PLID4">[View full width]</a></div><pre>
#include &lt;sys/socket.h&gt;

ssize_t recv(int <span class="docEmphItalicAlt">sockfd</span>, void *<span class="docEmphItalicAlt">buf</span>, size_t <span class="docEmphItalicAlt">nbytes</span>,
<img border="0" width="14" height="9" alt="" align="left" src="images/ccc.gif"> int <span class="docEmphItalicAlt">flags</span>);</pre><BR>

</p></TD></TR><tr><td class="docTableCell" align="right" valign="top"><p class="docText">Returns: length of message in bytes, 0 if no messages are available and peer has done an orderly shutdown, or 1 on error</p></td></TR></table></p><BR>
<p class="docText">The flags that can be passed to <tt>recv</tt> are summarized in <a class="docLink" href="#ch16fig12">Figure 16.12</a>. Only three are defined by the Single UNIX Specification.</p>
<a name="ch16fig12"></a><P><table cellspacing="0" class="allBorders" border="1" RULES="groups" cellpadding="5"><caption><h5 class="docTableTitle">Figure 16.12. Flags used with <tt>recv</tt> socket calls</h5></caption><colgroup><col width="100"><col width="150"><col width="50"><col width="50"><col width="50"><col width="50"><col width="50"></colgroup><thead><tr><th class="rightBorder bottomBorder thead" scope="col" align="center" valign="middle"><p class="docText"><span class="docEmphRoman">Flag</span></p></th><th class="rightBorder bottomBorder thead" scope="col" align="center" valign="middle"><p class="docText"><span class="docEmphRoman">Description</span></p></th><th class="rightBorder bottomBorder thead" scope="col" align="center" valign="middle"><p class="docText"><span class="docEmphRoman">POSIX.1</span></p></th><th class="rightBorder bottomBorder thead" scope="col" align="center" valign="middle"><p class="docText"><span class="docEmphRoman">FreeBSD 5.2.1</span></p></th><th class="rightBorder bottomBorder thead" scope="col" align="center" valign="middle"><p class="docText"><span class="docEmphRoman">Linux 5.2.1</span></p></th><th class="rightBorder bottomBorder thead" scope="col" align="center" valign="middle"><p class="docText"><span class="docEmphRoman">Mac OS X 10.3</span></p></th><th class="bottomBorder thead" scope="col" align="center" valign="middle"><p class="docText"><span class="docEmphRoman">Solaris 9</span></p></th></tr></thead><tr><td class="rightBorder" align="left" valign="top"><p class="docText"><tt>MSG_OOB</tt></p></td><td class="rightBorder" align="left" valign="top"><p class="docText">Retrieve out-of-band data if supported by protocol (see <a class="docLink" href="ch16lev1sec7.html#ch16lev1sec7">Section 16.7</a>).</p></TD><TD class="rightBorder" align="center" valign="top"><p class="docText">&#8226;</p></TD><TD class="rightBorder" align="center" valign="top"><p class="docText">&#8226;</P></td><TD class="rightBorder" align="center" valign="top"><p class="docText">&#8226;</P></TD><td class="rightBorder" align="center" valign="top"><p class="docText">&#8226;</P></td><TD class="docTableCell" align="center" valign="top"><p class="docText">&#8226;</P></TD></tr><TR><TD class="rightBorder" align="left" valign="top"><p class="docText"><tt>MSG_PEEK</tt></p></TD><TD class="rightBorder" align="left" valign="top"><p class="docText">Return packet contents without consuming packet.</p></td><td class="rightBorder" align="center" valign="top"><p class="docText">&#8226;</p></TD><td class="rightBorder" align="center" valign="top"><p class="docText">&#8226;</P></td><TD class="rightBorder" align="center" valign="top"><p class="docText">&#8226;</p></td><td class="rightBorder" align="center" valign="top"><p class="docText">&#8226;</p></td><td class="docTableCell" align="center" valign="top"><p class="docText">&#8226;</p></td></tr><tr><td class="rightBorder" align="left" valign="top"><p class="docText"><tt>MSG_TRUNC</tt></p></td><td class="rightBorder" align="left" valign="top"><p class="docText">Request that the real length of the packet be returned, even if it was truncated.</p></td><td class="rightBorder" align="left" valign="top">&nbsp;</TD><TD class="rightBorder" align="left" valign="top">&nbsp;</td><TD class="rightBorder" align="center" valign="top"><p class="docText">&#8226;</P></TD><td class="rightBorder" align="left" valign="top">&nbsp;</TD><TD class="docTableCell" align="left" valign="top">&nbsp;</TD></tr><TR><td class="rightBorder" align="left" valign="top"><p class="docText"><tt>MSG_WAITALL</tt></P></TD><TD class="rightBorder" align="left" valign="top"><p class="docText">Wait until all data is available (<tt>SOCK_STREAM</tt> only).</p></TD><TD class="rightBorder" align="center" valign="top"><p class="docText">&#8226;</p></TD><TD class="rightBorder" align="center" valign="top"><p class="docText">&#8226;</p></td><td class="rightBorder" align="center" valign="top"><p class="docText">&#8226;</p></TD><td class="rightBorder" align="center" valign="top"><p class="docText">&#8226;</P></td><TD class="docTableCell" align="center" valign="top"><p class="docText">&#8226;</p></td></tr></table></p><br>
<p class="docText">When we specify the <tt>MSG_PEEK</tt> flag, we can peek at the next data to be read without actually consuming it. The next call to <tt>read</tt> or one of the <tt>recv</tt> functions will return the same data we peeked at.</p>
<p class="docText">With <tt>SOCK_STREAM</tt> sockets, we can receive less data than we requested. The <tt>MSG_WAITALL</tt> flag inhibits this behavior, preventing <tt>recv</tt> from returning until all the data we requested has been received. With <tt>SOCK_DGRAM</tt> and <tt>SOCK_SEQPACKET</tt> sockets, the <tt>MSG_WAITALL</tt> flag provides no change in behavior, because these message-based socket types already return an entire message in a single read.</p>
<p class="docText">If the sender has called <tt>shutdown</tt> (<a class="docLink" href="ch16lev1sec2.html#ch16lev1sec2">Section 16.2</a>) to end transmission, or if the network protocol supports orderly shutdown by default and the sender has closed the socket, then <tt>recv</tt> will return 0 when we have received all the data.</p>
<p class="docText">If we are interested in the identity of the sender, we can use <tt>recvfrom</tt> to obtain the source address from which the data was sent.</p>
<a name="inta268"></a><p><table cellspacing="0" class="allBorders" border="1" RULES="none" cellpadding="5"><colgroup><col width="550"></colgroup><thead></thead><tr><td class="docTableCell" align="left" valign="top"><p class="docText">
<a name="PLID5"></a><div class="v1"><a href="ch16lev1sec5.html#PLID5">[View full width]</a></div><pre>
#include &lt;sys/socket.h&gt;

ssize_t recvfrom(int <span class="docEmphItalicAlt">sockfd</span>, void *restrict <span class="docEmphItalicAlt">buf</span>,
<img border="0" width="14" height="9" alt="" align="left" src="images/ccc.gif"> size_t <span class="docEmphItalicAlt">len</span>, int <span class="docEmphItalicAlt">flags</span>,
                 struct sockaddr *restrict <span class="docEmphasis">addr</span>,
                 socklen_t *restrict <span class="docEmphasis">addrlen</span>);
</pre><br>
</p></td></tr><tr><TD class="docTableCell" align="right" valign="top"><p class="docText">Returns: length of message in bytes, 0 if no messages are available and peer has done an orderly shutdown, or 1 on error</P></td></TR></table></P><BR>
<p class="docText"><a name="idd1e124400"></a><a name="idd1e124405"></a><a name="idd1e124410"></a><a name="idd1e124415"></a><a name="idd1e124420"></a><a name="idd1e124425"></a><a name="idd1e124430"></a><a name="idd1e124437"></a><a name="idd1e124442"></a>If <span class="docEmphasis">addr</span> is non-null, it will contain the address of the socket endpoint from which the data was sent. When calling <tt>recvfrom</tt>, we need to set the <span class="docEmphasis">addrlen</span> parameter to point to an integer containing the size in bytes of the socket buffer to which <span class="docEmphasis">addr</span> points. On return, the integer is set to the actual size of the address in bytes.</p>
<p class="docText">Because it allows us to retrieve the address of the sender, <tt>recvfrom</tt> is usually used with connectionless sockets. Otherwise, <tt>recvfrom</tt> behaves identically to <tt>recv</tt>.</P>
<p class="docText">To receive data into multiple buffers, similar to <tt>readv</tt> (<a class="docLink" href="ch14lev1sec7.html#ch14lev1sec7">Section 14.7</a>), or if we want to receive ancillary data (<a class="docLink" href="ch17lev1sec4.html#ch17lev2sec6">Section 17.4.2</a>), we can use <tt>recvmsg</tt>.</P>
<a name="inta269"></a><P><table cellspacing="0" class="allBorders" border="1" RULES="none" cellpadding="5"><colgroup><col width="550"></colgroup><thead></thead><tr><TD class="docTableCell" align="left" valign="top"><p class="docText">
<a name="PLID6"></a><div class="v1"><a href="ch16lev1sec5.html#PLID6">[View full width]</a></div><pre>
#include &lt;sys/socket.h&gt;

ssize_t recvmsg(int <span class="docEmphItalicAlt">sockfd</span>, struct msghdr *<span class="docEmphItalicAlt">msg</span>,
<img border="0" width="14" height="9" alt="" align="left" src="images/ccc.gif"> int <span class="docEmphItalicAlt">flags</span>);</pre><br>
</P></TD></TR><tr><TD class="docTableCell" align="right" valign="top"><p class="docText">Returns: length of message in bytes, 0 if no messages are available and peer has done an orderly shutdown, or 1 on error</P></td></TR></table></P><br>
<p class="docText">The <tt>msghdr</tt> structure (which we saw used with <tt>sendmsg</tt>) is used by <tt>recvmsg</tt> to specify the input buffers to be used to receive the data. We can set the <span class="docEmphasis">flags</span> argument to change the default behavior of <tt>recvmsg</tt>. On return, the <tt>msg_flags</tt> field of the <tt>msghdr</tt> structure is set to indicate various characteristics of the data received. (The <tt>msg_flags</tt> field is ignored on entry to <tt>recvmsg</tt>). The possible values on return from <tt>recvmsg</tt> are summarized in <a class="docLink" href="#ch16fig13">Figure 16.13</a>. We'll see an example that uses <tt>recvmsg</tt> in <a class="docLink" href="ch17.html#ch17">Chapter 17</a>.</p>
<a name="ch16fig13"></a><p><table cellspacing="0" class="allBorders" border="1" RULES="groups" cellpadding="5"><caption><h5 class="docTableTitle">Figure 16.13. Flags returned in <tt>msg_flags</tt> by <tt>recvmsg</tt></H5></caption><colgroup><col width="100"><col width="150"><col width="50"><col width="50"><col width="50"><col width="50"><col width="50"></colgroup><thead><tr><th class="rightBorder bottomBorder thead" scope="col" align="center" valign="middle"><p class="docText"><span class="docEmphRoman">Flag</span></P></th><th class="rightBorder bottomBorder thead" scope="col" align="center" valign="middle"><p class="docText"><span class="docEmphRoman">Description</span></p></th><th class="rightBorder bottomBorder thead" scope="col" align="center" valign="middle"><p class="docText"><span class="docEmphRoman">POSIX.1</span></P></th><th class="rightBorder bottomBorder thead" scope="col" align="center" valign="middle"><p class="docText"><span class="docEmphRoman">FreeBSD 5.2.1</span></p></th><th class="rightBorder bottomBorder thead" scope="col" align="center" valign="middle"><p class="docText"><span class="docEmphRoman">Linux 2.4.22</span></p></th><th class="rightBorder bottomBorder thead" scope="col" align="center" valign="middle"><p class="docText"><span class="docEmphRoman">Mac OS X 10.3</span></p></th><th class="bottomBorder thead" scope="col" align="center" valign="middle"><p class="docText"><span class="docEmphRoman">Solaris 9</span></p></th></tr></thead><tr><td class="rightBorder" align="left" valign="top"><p class="docText"><tt>MSG_CTRUNC</tt></p></td><td class="rightBorder" align="left" valign="top"><p class="docText">Control data was truncated.</p></td><td class="rightBorder" align="center" valign="top"><p class="docText">&#8226;</p></td><td class="rightBorder" align="center" valign="top"><p class="docText">&#8226;</p></TD><TD class="rightBorder" align="center" valign="top"><p class="docText">&#8226;</p></TD><TD class="rightBorder" align="center" valign="top"><p class="docText">&#8226;</P></td><TD class="docTableCell" align="center" valign="top"><p class="docText">&#8226;</P></TD></tr><TR><td class="rightBorder" align="left" valign="top"><p class="docText"><tt>MSG_DONTWAIT</tt></P></TD><TD class="rightBorder" align="left" valign="top"><p class="docText"><tt>recvmsg</tt> was called in nonblocking mode.</p></TD><TD class="rightBorder" align="left" valign="top">&nbsp;</td><TD class="rightBorder" align="left" valign="top">&nbsp;</TD><td class="rightBorder" align="center" valign="top"><p class="docText">&#8226;</p></td><td class="rightBorder" align="left" valign="top">&nbsp;</TD><td class="docTableCell" align="center" valign="top"><p class="docText">&#8226;</P></td></TR><tr><td class="rightBorder" align="left" valign="top"><p class="docText"><tt>MSG_EOR</tt></p></td><td class="rightBorder" align="left" valign="top"><p class="docText">End of record was received.</p></td><td class="rightBorder" align="center" valign="top"><p class="docText">&#8226;</p></td><td class="rightBorder" align="center" valign="top"><p class="docText">&#8226;</p></td><td class="rightBorder" align="center" valign="top"><p class="docText">&#8226;</p></td><td class="rightBorder" align="center" valign="top"><p class="docText">&#8226;</P></TD><td class="docTableCell" align="center" valign="top"><p class="docText">&#8226;</P></TD></TR><tr><TD class="rightBorder" align="left" valign="top"><p class="docText"><tt>MSG_OOB</tt></P></TD><td class="rightBorder" align="left" valign="top"><p class="docText">Out-of-band data was received.</P></td><TD class="rightBorder" align="center" valign="top"><p class="docText">&#8226;</P></TD><td class="rightBorder" align="center" valign="top"><p class="docText">&#8226;</P></TD><td class="rightBorder" align="center" valign="top"><p class="docText">&#8226;</P></TD><td class="rightBorder" align="center" valign="top"><p class="docText">&#8226;</p></td><td class="docTableCell" align="center" valign="top"><p class="docText">&#8226;</P></td></TR><tr><TD class="rightBorder" align="left" valign="top"><p class="docText"><tt>MSG_TRUNC</tt></p></td><td class="rightBorder" align="left" valign="top"><p class="docText">Normal data was truncated.</p></td><td class="rightBorder" align="center" valign="top"><p class="docText">&#8226;</p></td><td class="rightBorder" align="center" valign="top"><p class="docText">&#8226;</p></td><td class="rightBorder" align="center" valign="top"><p class="docText">&#8226;</p></td><td class="rightBorder" align="center" valign="top"><p class="docText">&#8226;</p></td><TD class="docTableCell" align="center" valign="top"><p class="docText">&#8226;</P></td></TR></table></P><BR>
<a name="ch16ex04"></a>
<h5 class="docExampleTitle">ExampleConnection-Oriented Client</H5>
<p class="docText"><a class="docLink" href="#ch16fig14">Figure 16.14</a> shows a client command that communicates with a server to obtain the output from a system's <tt>uptime</tt> command. We call this service &quot;remote uptime&quot; (or &quot;ruptime&quot; for short).</P>
<p class="docText"><a name="idd1e124808"></a><a name="idd1e124813"></a><a name="idd1e124818"></a><a name="idd1e124823"></a><a name="idd1e124828"></a><a name="idd1e124833"></a><a name="idd1e124838"></a><a name="idd1e124843"></a><a name="idd1e124848"></a><a name="idd1e124853"></a>This program connects to a server, reads the string sent by the server, and prints the string on the standard output. Since we're using a <tt>SOCK_STREAM</tt> socket, we can't be guaranteed that we will read the entire string in one call to <tt>recv</tt>, so we need to repeat the call until it returns 0.</P>
<p class="docText">The <tt>getaddrinfo</tt> function might return more than one candidate address for us to use if the server supports multiple network interfaces or multiple network protocols. We try each one in turn, giving up when we find one that allows us to connect to the service. We use the <tt>connect_retry</tt> function from <a class="docLink" href="ch16lev1sec4.html#ch16fig09">Figure 16.9</a> to establish a connection with the server.</p>

<a name="ch16fig14"></a>
<H5 class="docExampleTitle">Figure 16.14. Client command to get uptime from server</h5>

<pre>
#include "apue.h"
#include &lt;netdb.h&gt;
#include &lt;errno.h&gt;
#include &lt;sys/socket.h&gt;

#define MAXADDRLEN  256

#define BUFLEN      128

extern int connect_retry(int, const struct sockaddr *, socklen_t);

void
print_uptime(int sockfd)
{
    int     n;
    char    buf[BUFLEN];

    while ((n = recv(sockfd, buf, BUFLEN, 0)) &gt; 0)
        write(STDOUT_FILENO, buf, n);
    if (n &lt; 0)
        err_sys("recv error");
}

int
main(int argc, char *argv[])
{
    struct addrinfo *ailist, *aip;
    struct addrinfo hint;
    int             sockfd, err;

    if (argc != 2)
        err_quit("usage: ruptime hostname");
    hint.ai_flags = 0;
    hint.ai_family = 0;
    hint.ai_socktype = SOCK_STREAM;
    hint.ai_protocol = 0;
    hint.ai_addrlen = 0;
    hint.ai_canonname = NULL;
    hint.ai_addr = NULL;
    hint.ai_next = NULL;
    if ((err = getaddrinfo(argv[1], "ruptime", &amp;hint, &amp;ailist)) != 0)
        err_quit("getaddrinfo error: %s", gai_strerror(err));
    for (aip = ailist; aip != NULL; aip = aip-&gt;ai_next) {
        if ((sockfd = socket(aip-&gt;ai_family, SOCK_STREAM, 0)) &lt; 0)
            err = errno;
        if (connect_retry(sockfd, aip-&gt;ai_addr, aip-&gt;ai_addrlen) &lt; 0) {
            err = errno;
        } else {
            print_uptime(sockfd);
            exit(0);
        }
    }
    fprintf(stderr, "can't connect to %s: %s\n", argv[1],
      strerror(err));
    exit(1);
}
</pre><BR>


<a name="ch16ex05"></a>
<H5 class="docExampleTitle">ExampleConnection-Oriented Server</H5>
<p class="docText"><a name="idd1e124913"></a><a name="idd1e124918"></a><a name="idd1e124923"></a><a name="idd1e124928"></a><a name="idd1e124933"></a><a name="idd1e124938"></a><a name="idd1e124943"></a><a name="idd1e124948"></a><a class="docLink" href="#ch16fig15">Figure 16.15</a> shows the server that provides the <tt>uptime</tt> command's output to the client program from <a class="docLink" href="#ch16fig14">Figure 16.14</a>.</p>
<p class="docText"><a name="idd1e124967"></a><a name="idd1e124972"></a><a name="idd1e124975"></a><a name="idd1e124978"></a><a name="idd1e124983"></a>To find out its address, the server needs to get the name of the host on which it is running. Some systems don't define the <tt>_SC_HOST_NAME_MAX</tt> constant, so we use <tt>HOST_NAME_MAX</tt> in this case. If the system doesn't define <tt>HOST_NAME_MAX</tt>, we define it ourselves. POSIX.1 states that the minimum value for the host name is 255 bytes, not including the terminating null, so we define <tt>HOST_NAME_MAX</tt> to be 256 to include the terminating null.</P>
<p class="docText">The server gets the host name by calling <tt>gethostname</tt> and looks up the address for the remote uptime service. Multiple addresses can be returned, but we simply choose the first one for which we can establish a passive socket endpoint. Handling multiple addresses is left as an exercise.</P>
<p class="docText">We use the <tt>initserver</tt> function from <a class="docLink" href="ch16lev1sec4.html#ch16fig10">Figure 16.10</a> to initialize the socket endpoint on which we will wait for connect requests to arrive. (Actually, we use the version from <a class="docLink" href="ch16lev1sec6.html#ch16fig20">Figure 16.20</a>; we'll see why when we discuss socket options in <a class="docLink" href="ch16lev1sec6.html#ch16lev1sec6">Section 16.6</a>.)</p>

<a name="ch16fig15"></a>
<H5 class="docExampleTitle">Figure 16.15. Server program to provide system uptime</H5>

<pre>
#include "apue.h"
#include &lt;netdb.h&gt;
#include &lt;errno.h&gt;
#include &lt;syslog.h&gt;
#include &lt;sys/socket.h&gt;

#define BUFLEN  128
#define QLEN 10

#ifndef HOST_NAME_MAX
#define HOST_NAME_MAX 256
#endif

extern int initserver(int, struct sockaddr *, socklen_t, int);

void
serve(int sockfd)
{
    int     clfd;
    FILE    *fp;
    char    buf[BUFLEN];

    for (;;) {
        clfd = accept(sockfd, NULL, NULL);
        if (clfd &lt; 0) {
            syslog(LOG_ERR, "ruptimed: accept error: %s",
              strerror(errno));
            exit(1);
        }
        if ((fp = popen("/usr/bin/uptime", "r")) == NULL) {
            sprintf(buf, "error: %s\n", strerror(errno));
            send(clfd, buf, strlen(buf), 0);
        } else {
            while (fgets(buf, BUFLEN, fp) != NULL)
                send(clfd, buf, strlen(buf), 0);
            pclose(fp);
        }
        close(clfd);
    }
}

int
main(int argc, char *argv[])
{
    struct addrinfo *ailist, *aip;
    struct addrinfo hint;
    int             sockfd, err, n;
    char            *host;

    if (argc != 1)
        err_quit("usage: ruptimed");
#ifdef _SC_HOST_NAME_MAX
    n = sysconf(_SC_HOST_NAME_MAX);
    if (n &lt; 0)  /* best guess */
#endif
        n = HOST_NAME_MAX;
    host = malloc(n);
    if (host == NULL)
        err_sys("malloc error");
    if (gethostname(host, n) &lt; 0)
        err_sys("gethostname error");
    daemonize("ruptimed");
    hint.ai_flags = AI_CANONNAME;
    hint.ai_family = 0;
    hint.ai_socktype = SOCK_STREAM;
    hint.ai_protocol = 0;
    hint.ai_addrlen = 0;
    hint.ai_canonname = NULL;
    hint.ai_addr = NULL;
    hint.ai_next = NULL;
    if ((err = getaddrinfo(host, "ruptime", &amp;hint, &amp;ailist)) != 0) {
        syslog(LOG_ERR, "ruptimed: getaddrinfo error: %s",
          gai_strerror(err));
        exit(1);
    }
    for (aip = ailist; aip != NULL; aip = aip-&gt;ai_next) {
        if ((sockfd = initserver(SOCK_STREAM, aip-&gt;ai_addr,
          aip-&gt;ai_addrlen, QLEN)) &gt;= 0) {
            serve(sockfd);
            exit(0);
        }
    }
    exit(1);
}
</pre><br>


<a name="ch16ex06"></a>
<h5 class="docExampleTitle">ExampleAlternate Connection-Oriented Server</h5>
<p class="docText"><a name="idd1e125060"></a><a name="idd1e125065"></a><a name="idd1e125070"></a><a name="idd1e125075"></a><a name="idd1e125080"></a><a name="idd1e125085"></a><a name="idd1e125090"></a><a name="idd1e125095"></a><a name="idd1e125100"></a>Previously, we stated that using file descriptors to access sockets was significant, because it allowed programs that knew nothing about networking to be used in a networked environment. The version of the server shown in <a class="docLink" href="#ch16fig16">Figure 16.16</a> illustrates this point. Instead of reading the output of the <tt>uptime</tt> command and sending it to the client, the server arranges to have the standard output and standard error of the <tt>uptime</tt> command be the socket endpoint connected to the client.</p>
<p class="docText">Instead of using <tt>popen</tt> to run the <tt>uptime</tt> command and reading the output from the pipe connected to the command's standard output, we use <tt>fork</tt> to create a child process and then use <tt>dup2</tt> to arrange that the child's copy of <tt>STDIN_FILENO</tt> is open to <tt>/dev/null</tt> and that both <tt>STDOUT_FILENO</tt> and <tt>STDERR_FILENO</tt> are open to the socket endpoint. When we execute <tt>uptime</tt>, the command writes the results to its standard output, which is connected to the socket, and the data is sent back to the <tt>ruptime</tt> client command.</P>
<p class="docText">The parent can safely close the file descriptor connected to the client, because the child still has it open. The parent waits for the child to complete before proceeding, so that the child doesn't become a zombie. Since it shouldn't take too long to run the <tt>uptime</tt> command, the parent can afford to wait for the child to exit before accepting the next connect request. This strategy might not be appropriate if the child takes a long time, however.</p>

<a name="ch16fig16"></a>
<H5 class="docExampleTitle">Figure 16.16. Server program illustrating command writing directly to socket</h5>

<pre>
#include "apue.h"
#include &lt;netdb.h&gt;
#include &lt;errno.h&gt;
#include &lt;syslog.h&gt;
#include &lt;fcntl.h&gt;
#include &lt;sys/socket.h&gt;
#include &lt;sys/wait.h&gt;

#define QLEN 10

#ifndef HOST_NAME_MAX
#define HOST_NAME_MAX 256
#endif

extern int initserver(int, struct sockaddr *, socklen_t, int);

void
serve(int sockfd)
{
    int     clfd, status;
    pid_t   pid;

    for (;;) {
        clfd = accept(sockfd, NULL, NULL);
        if (clfd &lt; 0) {
            syslog(LOG_ERR, "ruptimed: accept error: %s",
              strerror(errno));
            exit(1);
        }
        if ((pid = fork()) &lt; 0) {
            syslog(LOG_ERR, "ruptimed: fork error: %s",
              strerror(errno));
            exit(1);
        } else if (pid == 0) {  /* child */
            /*
             * The parent called daemonize (Figure 13.1), so
             * STDIN_FILENO, STDOUT_FILENO, and STDERR_FILENO
             * are already open to /dev/null. Thus, the call to
             * close doesn't need to be protected by checks that
             * clfd isn't already equal to one of these values.
             */
            if (dup2(clfd, STDOUT_FILENO) != STDOUT_FILENO ||
              dup2(clfd, STDERR_FILENO) != STDERR_FILENO) {
                syslog(LOG_ERR, "ruptimed: unexpected error");
                exit(1);
            }
            close(clfd);
            execl("/usr/bin/uptime", "uptime", (char *)0);
            syslog(LOG_ERR, "ruptimed: unexpected return from exec: %s",
              strerror(errno));
        } else {        /* parent */
            close(clfd);
            waitpid(pid, &amp;status, 0);
        }
    }
}

int
main(int argc, char *argv[])
{
    struct addrinfo *ailist, *aip;
    struct addrinfo hint;
    int             sockfd, err, n;
    char            *host;

    if (argc != 1)
        err_quit("usage: ruptimed");
#ifdef _SC_HOST_NAME_MAX
    n = sysconf(_SC_HOST_NAME_MAX);
    if (n &lt; 0)  /* best guess */
#endif
        n = HOST_NAME_MAX;
    host = malloc(n);
    if (host == NULL)
        err_sys("malloc error");
    if (gethostname(host, n) &lt; 0)
        err_sys("gethostname error");
    daemonize("ruptimed");
    hint.ai_flags = AI_CANONNAME;
    hint.ai_family = 0;
    hint.ai_socktype = SOCK_STREAM;
    hint.ai_protocol = 0;
    hint.ai_addrlen = 0;
    hint.ai_canonname = NULL;
    hint.ai_addr = NULL;
    hint.ai_next = NULL;
    if ((err = getaddrinfo(host, "ruptime", &amp;hint, &amp;ailist)) != 0) {
        syslog(LOG_ERR, "ruptimed: getaddrinfo error: %s",
          gai_strerror(err));
        exit(1);
    }
    for (aip = ailist; aip != NULL; aip = aip-&gt;ai_next) {
        if ((sockfd = initserver(SOCK_STREAM, aip-&gt;ai_addr,
          aip-&gt;ai_addrlen, QLEN)) &gt;= 0) {
            serve(sockfd);
            exit(0);
        }
    }
    exit(1);
}
</pre><BR>


<p class="docText"><a name="idd1e125191"></a><a name="idd1e125196"></a><a name="idd1e125201"></a><a name="idd1e125206"></a><a name="idd1e125211"></a><a name="idd1e125216"></a><a name="idd1e125221"></a><a name="idd1e125226"></a><a name="idd1e125231"></a><a name="idd1e125236"></a><a name="idd1e125241"></a><a name="idd1e125246"></a><a name="idd1e125251"></a><a name="idd1e125256"></a><a name="idd1e125261"></a><a name="idd1e125266"></a><a name="idd1e125271"></a><a name="idd1e125276"></a><a name="idd1e125281"></a>The previous examples have used connection-oriented sockets. But how do we choose the appropriate type? When do we use a connection-oriented socket, and when do we use a connectionless socket? The answer depends on how much work we want to do and what kind of tolerance we have for errors.</p>
<p class="docText">With a connectionless socket, packets can arrive out of order, so if we can't fit all our data in one packet, we will have to worry about ordering in our application. The maximum packet size is a characteristic of the communication protocol. Also, with a connectionless socket, the packets can be lost. If our application can't tolerate this loss, we should use connection-oriented sockets.</p>
<p class="docText"><a name="idd1e125293"></a><a name="idd1e125298"></a><a name="idd1e125303"></a><a name="idd1e125308"></a><a name="idd1e125313"></a>Tolerating packet loss means that we have two choices. If we intend to have reliable communication with our peer, we have to number our packets and request retransmission from the peer application when we detect a missing packet. We will also have to identify duplicate packets and discard them, since a packet might be delayed and appear to be lost, but show up after we have requested retransmission.</p>
<p class="docText">The other choice we have is to deal with the error by letting the user retry the command. For simple applications, this might be adequate, but for complex applications, this usually isn't a viable alternative, so it is generally better to use connection-oriented sockets in this case.</p>
<p class="docText">The drawbacks to connection-oriented sockets are that more work and time are needed to establish a connection, and each connection consumes more resources from the operating system.</p>
<a name="ch16ex07"></a>
<h5 class="docExampleTitle">ExampleConnectionless Client</h5>
<p class="docText">The program in <a class="docLink" href="#ch16fig17">Figure 16.17</a> is a version of the <tt>uptime</tt> client command that uses the datagram socket interface.</p>
<p class="docText">The <tt>main</tt> function for the datagram-based client is similar to the one for the connection-oriented client, with the addition of installing a signal handler for <tt>SIGALRM</tt>. We use the <tt>alarm</tt> function to avoid blocking indefinitely in the call to <tt>recvfrom</tt>.</p>
<p class="docText">With the connection-oriented protocol, we needed to connect to the server before exchanging data. The arrival of the connect request was enough for the server to determine that it needed to provide service to a client. But with the datagram-based protocol, we need a way to notify the server that we want it to perform its service on our behalf. In this example, we simply send the server a 1-byte message. The server will receive it, get our address from the packet, and use this address to transmit its <a name="idd1e125359"></a><a name="idd1e125364"></a><a name="idd1e125369"></a><a name="idd1e125374"></a><a name="idd1e125379"></a><a name="idd1e125384"></a><a name="idd1e125389"></a><a name="idd1e125394"></a><a name="idd1e125399"></a><a name="idd1e125404"></a><a name="idd1e125409"></a><a name="idd1e125414"></a><a name="idd1e125419"></a>response. If the server offered multiple services, we could use this request message to indicate the service we want, but since the server does only one thing, the content of the 1-byte message doesn't matter.</p>
<p class="docText">If the server isn't running, the client will block indefinitely in the call to <tt>recvfrom</tt>. With the connection-oriented example, the <tt>connect</tt> call will fail if the server isn't running. To avoid blocking indefinitely, we set an alarm clock before calling <tt>recvfrom</tt>.</p>

<a name="ch16fig17"></a>
<h5 class="docExampleTitle">Figure 16.17. Client command using datagram service</h5>

<pre>
#include "apue.h"
#include &lt;netdb.h&gt;
#include &lt;errno.h&gt;
#include &lt;sys/socket.h&gt;

#define BUFLEN      128
#define TIMEOUT     20

void
sigalrm(int signo)
{
}

void
print_uptime(int sockfd, struct addrinfo *aip)
{
    int     n;
    char    buf[BUFLEN];

    buf[0] = 0;
    if (sendto(sockfd, buf, 1, 0, aip-&gt;ai_addr, aip-&gt;ai_addrlen) &lt; 0)
        err_sys("sendto error");
    alarm(TIMEOUT);
    if ((n = recvfrom(sockfd, buf, BUFLEN, 0, NULL, NULL)) &lt; 0) {
        if (errno != EINTR)
            alarm(0);
        err_sys("recv error");
    }
    alarm(0);
    write(STDOUT_FILENO, buf, n);
}
int
main(int argc, char *argv[])
{
    struct addrinfo     *ailist, *aip;
    struct addrinfo      hint;
    int                  sockfd, err;
    struct sigaction     sa;

    if (argc != 2)
        err_quit("usage: ruptime hostname");
    sa.sa_handler = sigalrm;
    sa.sa_flags = 0;
    sigemptyset(&amp;sa.sa_mask);
    if (sigaction(SIGALRM, &amp;sa, NULL) &lt; 0)
        err_sys("sigaction error");
    hint.ai_flags = 0;
    hint.ai_family = 0;
    hint.ai_socktype = SOCK_DGRAM;
    hint.ai_protocol = 0;
    hint.ai_addrlen = 0;
    hint.ai_canonname = NULL;
    hint.ai_addr = NULL;
    hint.ai_next = NULL;
    if ((err = getaddrinfo(argv[1], "ruptime", &amp;hint, &amp;ailist)) != 0)
        err_quit("getaddrinfo error: %s", gai_strerror(err));

    for (aip = ailist; aip != NULL; aip = aip-&gt;ai_next) {
        if ((sockfd = socket(aip-&gt;ai_family, SOCK_DGRAM, 0)) &lt; 0) {
            err = errno;
        } else {
            print_uptime(sockfd, aip);
            exit(0);
        }
     }

     fprintf(stderr, "can't contact %s: %s\n", argv[1], strerror(err));
     exit(1);
}
</pre><br>


<a name="ch16ex08"></a>
<h5 class="docExampleTitle">ExampleConnectionless Server</h5>
<p class="docText"><a name="idd1e125472"></a><a name="idd1e125477"></a><a name="idd1e125482"></a><a name="idd1e125487"></a><a name="idd1e125492"></a><a name="idd1e125497"></a><a name="idd1e125502"></a><a name="idd1e125507"></a><a name="idd1e125512"></a><a name="idd1e125517"></a>The program in <a class="docLink" href="#ch16fig18">Figure 16.18</a> is the datagram version of the <tt>uptime</tt> server.</p>
<p class="docText"><a name="idd1e125533"></a><a name="idd1e125538"></a><a name="idd1e125545"></a><a name="idd1e125550"></a><a name="idd1e125555"></a><a name="idd1e125560"></a><a name="idd1e125565"></a><a name="idd1e125570"></a><a name="idd1e125575"></a><a name="idd1e125580"></a><a name="idd1e125585"></a><a name="idd1e125592"></a><a name="idd1e125597"></a><a name="idd1e125602"></a><a name="idd1e125605"></a>The server blocks in <tt>recvfrom</tt> for a request for service. When a request arrives, we save the requester's address and use <tt>popen</tt> to run the <tt>uptime</tt> command. We send the output back to the client using the <tt>sendto</tt> function, with the destination address set to the requester's address.</P>

<a name="ch16fig18"></a>
<H5 class="docExampleTitle">Figure 16.18. Server providing system uptime over datagrams</h5>

<pre>
#include "apue.h"
#include &lt;netdb.h&gt;
#include &lt;errno.h&gt;
#include &lt;syslog.h&gt;
#include &lt;sys/socket.h&gt;

#define BUFLEN      128
#define MAXADDRLEN  256

#ifndef HOST_NAME_MAX
#define HOST_NAME_MAX 256
#endif

extern int initserver(int, struct sockaddr *, socklen_t, int);

void
serve(int sockfd)
{
    int         n;
    socklen_t   alen;
    FILE        *fp;
    char        buf[BUFLEN];
    char        abuf[MAXADDRLEN];

    for (;;) {
        alen = MAXADDRLEN;
        if ((n = recvfrom(sockfd, buf, BUFLEN, 0,
          (struct sockaddr *)abuf, &amp;alen)) &lt; 0) {
            syslog(LOG_ERR, "ruptimed: recvfrom error: %s",
              strerror(errno));
            exit(1);
        }
        if ((fp = popen("/usr/bin/uptime", "r")) == NULL) {
            sprintf(buf, "error: %s\n", strerror(errno));
            sendto(sockfd, buf, strlen(buf), 0,
              (struct sockaddr *)abuf, alen);
        } else {
            if (fgets(buf, BUFLEN, fp) != NULL)
                sendto(sockfd, buf, strlen(buf), 0,

                  (struct sockaddr *)abuf, alen);
            pclose(fp);
        }

    }

}

int
main(int argc, char *argv[])
{
    struct addrinfo *ailist, *aip;
    struct addrinfo hint;
    int             sockfd, err, n;
    char            *host;

    if (argc != 1)
        err_quit("usage: ruptimed");
#ifdef _SC_HOST_NAME_MAX
    n = sysconf(_SC_HOST_NAME_MAX);
    if (n &lt; 0)  /* best guess */
#endif
        n = HOST_NAME_MAX;
    host = malloc(n);
    if (host == NULL)
        err_sys("malloc error");
    if (gethostname(host, n) &lt; 0)
        err_sys("gethostname error");
    daemonize("ruptimed");
    hint.ai_flags = AI_CANONNAME;
    hint.ai_family = 0;
    hint.ai_socktype = SOCK_DGRAM;
    hint.ai_protocol = 0;
    hint.ai_addrlen = 0;
    hint.ai_canonname = NULL;
    hint.ai_addr = NULL;
    hint.ai_next = NULL;
    if ((err = getaddrinfo(host, "ruptime", &amp;hint, &amp;ailist)) != 0) {
        syslog(LOG_ERR, "ruptimed: getaddrinfo error: %s",
          gai_strerror(err));
        exit(1);
    }
    for (aip = ailist; aip != NULL; aip = aip-&gt;ai_next) {
        if ((sockfd = initserver(SOCK_DGRAM, aip-&gt;ai_addr,
          aip-&gt;ai_addrlen, 0)) &gt;= 0) {
            serve(sockfd);
            exit(0);
        }
    }
    exit(1);
}
</pre><BR>



<a href="17021535.html"><img src="images/pixel.gif" alt="" width="1" height="1" border="0"></a><UL></UL></td></TR></table>
<table width="100%" border="0" cellspacing="0" cellpadding="0">
<tr><td><div STYLE="MARGIN-LEFT: 0.15in;"><a href="toc.html"><img src="images/team.gif" width="60" height="17" border="0" align="absmiddle"  alt="Team BBL"></a></div></td>
<td align="right"><div STYLE="MARGIN-LEFT: 0.15in;">
<a href=ch16lev1sec4.html><img src="images/prev.gif" width="60" height="17" border="0" align="absmiddle" alt="Previous Page"></a>
<a href=ch16lev1sec6.html><img src="images/next.gif" width="60" height="17" border="0" align="absmiddle" alt="Next Page"></a>
</div></td></tr></table>
</body></html><br>
<table width="100%" cellspacing="0" cellpadding="0"
style="margin-top: 0pt; border-collapse: collapse;"> 
<tr> <td align="right" style="background-color=white; border-top: 1px solid gray;"> 
<a href="http://www.zipghost.com/" target="_blank" style="font-family: Tahoma, Verdana;
 font-size: 11px; text-decoration: none;">The CHM file was converted to HTM by Trial version of <b>ChmD<!--188-->ecompiler</b>.</a>
</TD>
</TR><tr>
<td align="right" style="background-color=white; "> 
<a href="http://www.etextwizard.com/download/cd/cdsetup.exe" target="_blank" style="font-family: Tahoma, Verdana;
 font-size: 11px; text-decoration: none;">Download <b>ChmDec<!--188-->ompiler</b> at: http://www.zipghost.com</a>
</TD></tr></table>
